package com.dhcc.bpm.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tool.api.R;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.UUID;
import java.util.concurrent.*;

/**
 * @Title
 * @ClassName OpenapiGenerator
 * @Desription
 * @Author zhangzexu
 * @Date 2020/6/8 14:33
 * @Version V1.0
 */
@Slf4j
@Component
public class OpenapiGeneratorUtils {

    @Value("${bpm.mvn-home}")
    private String mvnHome;

    private String path;



    ExecutorService threadExecutor = new ThreadPoolExecutor(0, Runtime.getRuntime().availableProcessors() == 1 ? 1 : Runtime.getRuntime().availableProcessors() -1,
            20L, TimeUnit.SECONDS,
            new SynchronousQueue<Runnable>());

    public OpenapiGeneratorUtils() throws Exception {
        path = new File("bin").getAbsolutePath();
        log.info("代码生成插件目录为{}", path);
        if (!new File(path).exists()) {
            throw new Exception("代码生成插件 不存在"+path);
        }
    }

    public String getPath() {
        return path;
    }

    public R makeClient(String apiYamlPath, String outputPath, String groupId, String artifactId, String artifactVersion, String invokerPackage, String apiPackage, String modelPackage) {
        log.info("apiYaml:{},outputPath:{}", apiYamlPath, outputPath);

        if (!new File(apiYamlPath).exists()) {
            return R.fail("yaml文件不存在!");
        }

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("cd "+path+"&&");
        stringBuilder.append("cat banner.txt&&");
        stringBuilder.append("echo java sdk 生成开始&&");


        stringBuilder.append("java  -XX:MaxPermSize=256M -Xmx1024M -jar openapi-generator-cli.jar generate -t okhttp-gson");
        stringBuilder.append(" -i " + apiYamlPath);
        stringBuilder.append(" -g java");
        stringBuilder.append(" -o " + outputPath+"Client");
        stringBuilder.append(" --group-id=" + groupId);
        stringBuilder.append(" --artifact-id=" + artifactId);
        stringBuilder.append(" --artifact-version=" + artifactVersion);
        if (!StringUtils.isEmpty(invokerPackage)) {
            stringBuilder.append(" --invoker-package=" + invokerPackage);
        } else {
            stringBuilder.append(" --invoker-package=" + groupId);
        }


        if (!StringUtils.isEmpty(invokerPackage)) {
            stringBuilder.append(" --api-package=" + invokerPackage + ".controller");
        } else {
            stringBuilder.append(" --api-package=" + groupId + ".controller");
        }

        if (!StringUtils.isEmpty(invokerPackage)) {
            stringBuilder.append(" --model-package=" + invokerPackage + ".model");
        } else {
            stringBuilder.append(" --model-package=" + groupId + ".model");
        }

        stringBuilder.append(" --skip-overwrite");
        stringBuilder.append(" --additional-properties hideGenerationTimestamp=true &&");


        stringBuilder.append("cd "+outputPath+"Client &&");

        String mvnCmd = "clean install";

        try (RandomAccessFile br = new RandomAccessFile(path+"/repository.xml", "r")){
            String str = br.readLine();
            if(StringUtils.isEmpty(str)){
            }else {
                stringBuilder.append("sed -i 's/<\\/project>/");
                stringBuilder.append(str);
                stringBuilder.append("/g' pom.xml &&");
                mvnCmd = mvnCmd+" deploy";
            }
        }catch (Exception e){
            log.error("文件读取失败{}",e);
        }



        stringBuilder.append(mvnHome + "/bin/mvn "+mvnCmd+" &&");

        stringBuilder.append("cp target/" + artifactId + "-" + artifactVersion + ".jar " + apiYamlPath.replace("proCode.yaml", ""));

        stringBuilder.append("&&rm -rf " + outputPath+"Client");


        stringBuilder.append("&&echo openapi HTML使用文档生成开始&&");

        stringBuilder.append("cd "+path+"&&");


        stringBuilder.append("java -jar swagger-codegen-cli.jar generate -l html2");
        stringBuilder.append(" -i " + apiYamlPath);
        stringBuilder.append(" -o " + outputPath+"Html2");

        stringBuilder.append(" --additional-properties hideGenerationTimestamp=true &&");

        stringBuilder.append("cp " + outputPath+"Html2" + "/index.html " + apiYamlPath.replace("proCode.yaml", ""));



        stringBuilder.append("&& rm -rf "+outputPath+"Html2");

        stringBuilder.append("&&echo openapi HTML使用文档生成结束");
        stringBuilder.append("&&echo success ok");


        return R.success(execBackCmd(stringBuilder.toString()));
    }


    public R makeOpenapiServer(String apiYamlPath, String outputPath, String groupId, String artifactId, String artifactVersion, String invokerPackage, String apiPackage, String modelPackage) {
        String result = "";

        if (!new File(apiYamlPath).exists()) {
            return R.fail("yaml文件不存在!");
        }

        StringBuilder stringBuilder = new StringBuilder();

        stringBuilder.append("cd "+path+"&&");
        stringBuilder.append("cat banner.txt&&");
        stringBuilder.append("echo java server 端代码生成开始&&");

        stringBuilder.append("java  -XX:MaxPermSize=256M -Xmx1024M -jar openapi-generator-cli.jar generate -t JavaSpring");
        stringBuilder.append(" -i " + apiYamlPath);
        stringBuilder.append(" -g spring");
        stringBuilder.append(" -o " + outputPath);
        stringBuilder.append(" --group-id=" + groupId);
        stringBuilder.append(" --artifact-id=" + artifactId);
        stringBuilder.append(" --artifact-version=" + artifactVersion);
        if (!StringUtils.isEmpty(invokerPackage)) {
            stringBuilder.append(" --invoker-package=" + invokerPackage);
        } else {
            stringBuilder.append(" --invoker-package=" + groupId);
        }


        if (!StringUtils.isEmpty(invokerPackage)) {
            stringBuilder.append(" --api-package=" + invokerPackage + ".controller");
        } else {
            stringBuilder.append(" --api-package=" + groupId + ".controller");
        }

        if (!StringUtils.isEmpty(invokerPackage)) {
            stringBuilder.append(" --model-package=" + invokerPackage + ".model");
        } else {
            stringBuilder.append(" --model-package=" + groupId + ".model");
        }

        stringBuilder.append(" --skip-overwrite");
        stringBuilder.append(" --additional-properties hideGenerationTimestamp=true&&");

        stringBuilder.append("echo java server 端代码生成结束&&");

        stringBuilder.append("echo success ok");

        result = execBackCmd(stringBuilder.toString());

        return R.success(result);
    }



    public String execCmd(String cmd) {
        Process p;
        String result = "";
        log.info("执行的命令为 {}",cmd);
        try {
            String[] exec = {"/bin/sh", "-c", cmd};

            //执行命令
            p = Runtime.getRuntime().exec(exec);
            //取得命令结果的输出流
            InputStream fis = p.getInputStream();
            //用一个读输出流类去读
            InputStreamReader isr = new InputStreamReader(fis);
            //用缓冲器读行
            BufferedReader br = new BufferedReader(isr);
            String line = null;
            //直到读完为止
            while ((line = br.readLine()) != null) {
                log.info("cmd 命令执行结果{}",line);
                result = result + line + "\n";
            }
            return result;
        } catch (IOException e) {
            log.error("执行cmd 命令出现异常");
            return "";
        }

    }

    public String execBackCmd(String cmd) {
        StringBuilder stringBuilder = new StringBuilder();
        String binName = System.currentTimeMillis() + UUID.randomUUID().toString() + ".sh";
        String logName = System.currentTimeMillis() + UUID.randomUUID().toString() + ".log";
        threadExecutor.execute(new Runnable() {
            @Override
            public void run() {
                execCmd("cd bin/log&&cat >> "+binName+" <<EOF\n" +
                        cmd+"\n" +
                        "EOF");
                execCmd("cd bin/log&&chmod 755 "+binName);
                stringBuilder.append("cd bin/log&&nohup ./" + binName + " > ");
                stringBuilder.append(logName);
                stringBuilder.append(" 2>&1 &");
                execCmd(stringBuilder.toString());
                execCmd("cd bin/log&&rm -rf "+binName);
            }
        });
        return logName;
    }


}
